﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace WeChatGZHTextExtractor.DB
{
    public static class GlobalLock
    {
        private static object g_lock = new object();

        public static object GetLock<T>()
        {
            return g_lock;
        }
    }

    public class BaseProvider<T> : DbContext
        where T : BaseModel
    {
        public DbSet<T> Context { get; set; }

        public string TableName { get; set; }

        public BaseProvider()
        {
            var t_type = typeof(T);
            var tablename_attribute = t_type.GetCustomAttribute<TableNameAttribute>();

            if (tablename_attribute != null)
            {
                TableName = tablename_attribute.TableName;
            }
            else
            {
                if (t_type.Name.EndsWith("Model"))
                {
                    TableName = t_type.Name.Substring(0, t_type.Name.Length - "Model".Length);
                }
                else
                {
                    TableName = t_type.Name;
                }
            }
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            base.OnConfiguring(optionsBuilder);

            optionsBuilder.UseMySQL("Server=weixindb;Port=3306;Stmt=;Database=WeChatGZHTextExtractor; User=root;Password=123456;Character Set=utf8");
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<T>().ToTable(TableName);
        }
    }

    public class BaseService<T>
        where T : BaseModel
    {
        protected BaseProvider<T> provider = new BaseProvider<T>();

        /// <summary>
        /// 查询数据
        /// </summary>
        /// <typeparam name="B"></typeparam>
        /// <param name="query_func"></param>
        /// <returns></returns>
        public B Query<B>(Func<DbSet<T>, B> query_func = null)
        {
            if (query_func == null)
                return default(B);

            lock (GlobalLock.GetLock<T>())
                return query_func.Invoke(provider.Context);
        }

        /// <summary>
        /// 改变数据
        /// </summary>
        /// <param name="change_action"></param>
        public void Change(Action<DbSet<T>> change_action = null)
        {
            lock (GlobalLock.GetLock<T>())
            {
                change_action?.Invoke(provider.Context);
                provider.SaveChanges();
            }
        }
    }
}
